use poem::{web::Json, IntoResponse, Response};
use serde::Serialize;
use serde_repr::Serialize_repr;

#[derive(Serialize_repr)]
#[repr(u8)]
pub enum Code {
    OK = 0,
    NoItem = 1,
    WrongPassword = 2,
    DuplicateItem = 3,
}

#[derive(Serialize)]
pub struct Reply<T = ()> {
    code: Code,
    #[serde(rename(serialize = "message"))]
    msg: Option<String>,
    data: Option<T>,
}

impl<T: Serialize + Send> IntoResponse for Reply<T> {
    fn into_response(self) -> Response {
        Json(self).into_response()
    }
}

impl<T: Serialize> Reply<T> {
    pub fn new() -> Self {
        Self {
            code: Code::OK,
            msg: None,
            data: None,
        }
    }

    pub fn code(mut self, code: Code) -> Self {
        self.code = code;

        self
    }

    pub fn msg(mut self, msg: impl Into<String>) -> Self {
        self.msg = Some(msg.into());

        self
    }

    pub fn data(mut self, data: T) -> Self {
        self.data = Some(data);

        self
    }

    pub fn set_code(&mut self, code: Code) -> &mut Self {
        self.code = code;

        self
    }

    pub fn set_msg(&mut self, msg: impl Into<String>) -> &mut Self {
        self.msg = Some(msg.into());

        self
    }
}
